<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8" />
    <title>React 实例</title>
    <script src="https://cdn.staticfile.org/react/16.4.0/umd/react.development.js"></script>
    <script src="https://cdn.staticfile.org/react-dom/16.4.0/umd/react-dom.development.js"></script>
    <script src="https://cdn.staticfile.org/babel-standalone/6.26.0/babel.min.js"></script>
    <style>
        body {
            font: 14px "Century Gothic", Futura, sans-serif;
            margin: 20px;
        }

        ol, ul {
            padding-left: 30px;
        }

        .board-row:after {
            clear: both;
            content: "";
            display: table;
        }

        .status {
            margin-bottom: 10px;
        }

        .square {
            background: #fff;
            border: 1px solid #999;
            float: left;
            font-size: 24px;
            font-weight: bold;
            line-height: 34px;
            height: 34px;
            margin-right: -1px;
            margin-top: -1px;
            padding: 0;
            text-align: center;
            width: 34px;
        }

        .square:focus {
            outline: none;
        }

        .kbd-navigation .square:focus {
            background: #ddd;
        }

        .game {
            display: flex;
            flex-direction: row;
        }

        .game-info {
            margin-left: 20px;
        }
    </style>
</head>
<body>

<script type="text/babel">
    function Square(props) {
        return (
                <button className="square" onClick={props.onClick}>
        {props.value}
    </button>
    );
    }

    class Board extends React.Component {
        renderSquare(i) {
            return (
                    <Square
            value={this.props.squares[i]}
            onClick={() => this.props.onClick(i)}
        />
        );
        }

        render() {
            return (
                    <div>
                    <div className="board-row">
                    {this.renderSquare(0)}
            {this.renderSquare(1)}
            {this.renderSquare(2)}
        </div>
            <div className="board-row">
                    {this.renderSquare(3)}
            {this.renderSquare(4)}
            {this.renderSquare(5)}
        </div>
            <div className="board-row">
                    {this.renderSquare(6)}
            {this.renderSquare(7)}
            {this.renderSquare(8)}
        </div>
            </div>
        );
        }
    }

    class Game extends React.Component {
        constructor(props) {
            super(props);
            this.state = {
                history: [
                    {
                        squares: Array(9).fill(null)
                    }
                ],
                stepNumber: 0,
                xIsNext: true
            };
        }

        handleClick(i) {
            const history = this.state.history.slice(0, this.state.stepNumber + 1);
            const current = history[history.length - 1];
            const squares = current.squares.slice();
            if (calculateWinner(squares) || squares[i]) {
                return;
            }
            squares[i] = this.state.xIsNext ? "X" : "O";
            this.setState({
                history: history.concat([
                    {
                        squares: squares
                    }
                ]),
                stepNumber: history.length,
                xIsNext: !this.state.xIsNext
            });
        }

        jumpTo(step) {
            this.setState({
                stepNumber: step,
                xIsNext: (step % 2) === 0
            });
        }

        render() {
            const history = this.state.history;
            const current = history[this.state.stepNumber];
            const winner = calculateWinner(current.squares);

            const moves = history.map((step, move) => {
                const desc = move ?
                'Go to move #' + move :
                        'Go to game start';
                return (
                        <li key={move}>
                        <button onClick={() => this.jumpTo(move)}>{desc}</button>
                </li>
                );
            });

            let status;
            if (winner) {
                status = "Winner: " + winner;
            } else {
                status = "Next player: " + (this.state.xIsNext ? "X" : "O");
            }

            return (
                    <div className="game">
                    <div className="game-board">
                    <Board
            squares={current.squares}
            onClick={i => this.handleClick(i)}
        />
        </div>
            <div className="game-info">
                    <div>{status}</div>
                    <ol>{moves}</ol>
                    </div>
                    </div>
        );
        }
    }

    // ========================================

    ReactDOM.render(<Game />, document.getElementById("root"));

    function calculateWinner(squares) {
        const lines = [
            [0, 1, 2],
            [3, 4, 5],
            [6, 7, 8],
            [0, 3, 6],
            [1, 4, 7],
            [2, 5, 8],
            [0, 4, 8],
            [2, 4, 6]
        ];
        for (let i = 0; i < lines.length; i++) {
            const [a, b, c] = lines[i];
            if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
                return squares[a];
            }
        }
        return null;
    }
</script>

<div id="errors" style="
  background: #c00;
  color: #fff;
  display: none;
  margin: -20px -20px 20px;
  padding: 20px;
  white-space: pre-wrap;"></div>
<div id="root"></div>
<script>
    window.addEventListener('mousedown', function(e) {
        document.body.classList.add('mouse-navigation');
        document.body.classList.remove('kbd-navigation');
    });
    window.addEventListener('keydown', function(e) {
        if (e.keyCode === 9) {
            document.body.classList.add('kbd-navigation');
            document.body.classList.remove('mouse-navigation');
        }
    });
    window.addEventListener('click', function(e) {
        if (e.target.tagName === 'A' && e.target.getAttribute('href') === '#') {
            e.preventDefault();
        }
    });
    window.onerror = function(message, source, line, col, error) {
        var text = error ? error.stack || error : message + ' (at ' + source + ':' + line + ':' + col + ')';
        errors.textContent += text + '\n';
        errors.style.display = '';
    };
    console.error = (function(old) {
        return function error() {
            errors.textContent += Array.prototype.slice.call(arguments).join(' ') + '\n';
            errors.style.display = '';
            old.apply(this, arguments);
        }
    })(console.error);
</script>

</body>
</html>